package drds.plus.rule_engine.column_value_enumerator.handler.number;

import drds.plus.common.model.comparative.Comparative;
import drds.plus.rule_engine.column_value_enumerator.handler.PartDiscontinousRangeEnumerateHandler;

import java.util.Set;

public abstract class NumberPartDiscontinousRangeEnumerateHandler extends PartDiscontinousRangeEnumerateHandler {

    protected static final int LIMIT_UNIT_OF_LONG = 1;
    protected static final int DEFAULT_LONG_ATOMIC_VALUE = 1;

    protected Comparative changeGreaterThanToGreaterThanOrEqual(Comparative from) {
        if (from.getComparison() == Comparative.greater_than) {
            Number fromComparable = cast2Number(from.getValue());
            return new Comparative(Comparative.greater_than_or_equal, (Comparable) plus(fromComparable, LIMIT_UNIT_OF_LONG));
        } else {
            return from;
        }
    }

    protected Comparative changeLessThanToLessThanOrEqual(Comparative to) {
        if (to.getComparison() == Comparative.less_than) {
            Number toComparable = cast2Number(to.getValue());
            return new Comparative(Comparative.less_than_or_equal, (Comparable) plus(toComparable, -1 * LIMIT_UNIT_OF_LONG));
        } else {
            return to;
        }
    }

    protected Comparable getOneStep(Comparable source, Comparable atomIncreaseValue) {
        if (atomIncreaseValue == null) {
            atomIncreaseValue = DEFAULT_LONG_ATOMIC_VALUE;
        }
        Number sourceLong = cast2Number(source);
        int atomIncValInt = (Integer) atomIncreaseValue;
        return (Comparable) plus(sourceLong, atomIncValInt);
    }

    protected boolean inputCloseRangeGreaterThanMaxFieldOfDifination(Comparable from, Comparable to, Integer cumulativeTimes, Comparable<?> atomIncrValue) {
        if (cumulativeTimes == null) {
            return false;
        }
        if (atomIncrValue == null) {
            atomIncrValue = DEFAULT_LONG_ATOMIC_VALUE;
        }
        long fromLong = ((Number) from).longValue();
        long toLong = ((Number) to).longValue();
        int atomIncValLong = ((Number) atomIncrValue).intValue();
        int size = cumulativeTimes;
        return (toLong - fromLong) > (atomIncValLong * size);
    }

    public void exhaust(Comparative from, Integer cumulativeTime, Comparable<?> atomIncreaseValue, Set<Object> returnSet) {
        if (cumulativeTime == null) {
            throw new IllegalStateException("在没有提供叠加次数的前提下，不能够根据当前范围条件选出对应的定义域的枚举值，sql中不要出现> < >= <=");
        }
        if (atomIncreaseValue == null) {
            atomIncreaseValue = DEFAULT_LONG_ATOMIC_VALUE;
        }
        // 把> < 替换为>= <=
        from = changeGreaterThanToGreaterThanOrEqual(from);
        from = changeLessThanToLessThanOrEqual(from);

        // long beginInt = (Long) toPrimaryValue(begin.getValue());
        Number beginInt = getNumber(from.getValue());
        int atomicIncreateValueInt = ((Number) atomIncreaseValue).intValue();
        int comparasion = from.getComparison();

        if (comparasion == Comparative.greater_than_or_equal) {
            for (int i = 0; i < cumulativeTime; i++) {
                returnSet.add(plus(beginInt, atomicIncreateValueInt * i));
            }
        } else if (comparasion == Comparative.less_than_or_equal) {
            for (int i = 0; i < cumulativeTime; i++) {
                Number value = plus(beginInt, -1 * atomicIncreateValueInt * i);
                if (value.longValue() < 0) {// 不允许出现负数
                    break;
                }
                returnSet.add(value);
            }
        }
    }

    protected abstract Number cast2Number(Comparable begin);

    protected abstract Number getNumber(Comparable begin);

    protected abstract Number plus(Number begin, int plus);
}
